<template>
  <template
    v-if="
      (hasOneShowingChild(item.children, item) &&
        !item.meta?.alwaysShow &&
        (!onlyOneChild.children || onlyOneChild.noShowingChildren)) ||
      (item.meta?.alwaysShow && !item.children)
    "
  >
    <Menu.Item :title="onlyOneChild.meta.title" :key="resolvePath(onlyOneChild.path)">
      <MenuItemContent
        v-if="onlyOneChild.meta"
        :icon="onlyOneChild.meta.icon || item.meta?.icon"
        :title="collapsed ? '' : onlyOneChild.meta.title"
      />
    </Menu.Item>
  </template>
  <Menu.SubMenu v-else :key="resolvePath(item.path)">
    <template #title>
      <MenuItemContent v-if="item.meta" :icon="item.meta.icon" :title="item.meta.title" />
    </template>

    <MenuItem
      v-for="child in item.children"
      :key="child.path"
      :is-nest="true"
      :item="child"
      :base-path="resolvePath(child.path)"
    />
  </Menu.SubMenu>
</template>

<script setup>
import { Menu } from 'ant-design-vue'
import { ref } from 'vue'
import path from 'path-browserify'
import AppLink from '@/components/AppLink/index.vue'
import MenuItemContent from './MenuItemContent.vue'
import { isExternal } from '@/utils'
defineOptions({
  name: 'MenuItem',
  inheritAttrs: false,
})

const props = defineProps({
  /**
   * 当前路由对象
   */
  item: {
    type: Object,
    required: true,
  },
  /**
   * 父级完整路径
   */
  basePath: {
    type: String,
    required: true,
  },

  /**
   * 是否为嵌套路由
   */
  isNest: {
    type: Boolean,
    default: false,
  },
  collapsed: {
    type: Boolean,
    default: false,
  },
})

// 可见的唯一子节点
const onlyOneChild = ref()

/**
 * 检查是否仅有一个可见子节点
 *
 * @param children 子路由数组
 * @param parent 父级路由
 * @returns 是否仅有一个可见子节点
 */
function hasOneShowingChild(children = [], parent) {
  // 过滤出可见子节点
  const showingChildren = children.filter((route) => {
    if (!route.meta?.hidden) {
      onlyOneChild.value = route
      return true
    }
    return false
  })

  // 仅有一个节点
  if (showingChildren.length === 1) {
    return true
  }

  // 无子节点时
  if (showingChildren.length === 0) {
    // 父节点设置为唯一显示节点，并标记为无子节点
    onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
    return true
  }
  return false
}

/**
 * 获取完整路径，适配外部链接
 *
 * @param routePath 路由路径
 * @returns 绝对路径
 */
function resolvePath(routePath) {
  if (isExternal(routePath)) return routePath
  if (isExternal(props.basePath)) return props.basePath

  // 拼接父路径和当前路径
  return path.resolve(props.basePath, routePath)
}
</script>

<style lang="scss" scoped></style>
